package owg.util.editor2d.operations;

import java.util.ArrayList;
import java.util.List;

import owg.util.data.KryoInstance.K;
import owg.util.data.Pair;
import owg.util.editor2d.ConstructorParams;
import owg.util.editor2d.Editor2D;
import owg.util.editor2d.entity.Placeable2D;

public class Destroyer extends Operation
{
	private final Integer[] indicesToDelete;
	/**The list of destroyed objects. Note that this is only used for reviving the objects.
	 * If the objects are un-created, recreated and re-destroyed, then this list will be updated, ensuring safety of operation.*/
	private ArrayList<Pair<Placeable2D, ConstructorParams>> destroyedObjects;
	private int[] reinsertionIndices;
	//private LinkData[] restoreLinkData;
	@K private Destroyer(){indicesToDelete = null;}
	/**
	 * @param selected The indices in the world objects which will be deleted.
	 * These must be indices and not references because objects may be destroyed and reconstructed.
	 */
	public Destroyer(Integer[] selected)
	{
		this.indicesToDelete = selected;
		destroyedObjects = null;
		reinsertionIndices = null;
		//restoreLinkData = null;
	}
	
	@Override
	public void apply(Editor2D w) throws OperationFailedException
	{
		//Construct list of objects at our indices
		//Also, discover all Linkables within a link distance of 1 from the selected objects
		//HashSet<Linkable> affectedLinks = new HashSet<Linkable>(); TODO this stuff
		List<Pair<Placeable2D,ConstructorParams>> worldObjects = w.worldObjectsImmutable;
		destroyedObjects = new ArrayList<Pair<Placeable2D,ConstructorParams>>(indicesToDelete.length);
		for(int i = 0; i<indicesToDelete.length; i++)
		{
			Pair<Placeable2D, ConstructorParams> p = worldObjects.get(indicesToDelete[i]);
			destroyedObjects.add(p);
			/*if(p.a instanceof Linkable)
			{
			affectedLinks.add((Linkable) p.a);
			for(Linkable l : ((Linkable) p.a).getLinks())
				affectedLinks.add(l);
			}*/
		}
		/*Linkable[] set = new Linkable[affectedLinks.size()];
	affectedLinks.toArray(set);*/
		//It is now necessary to keep a list of references because these objects can be revived by a Reviver.
		//Also, remember the links of all linkables that might be affected.
		/*restoreLinkData = new LinkData[set.length];
	for(int i = 0; i<set.length; i++)
		{
		restoreLinkData[i] = new LinkData(set[i]); 
		}
		 */
		for (Pair<Placeable2D,ConstructorParams> p : destroyedObjects)
		{
			/*if(p.a instanceof Linkable)
			{
			for(Linkable l : ((Linkable) p.a).getLinks())
				((Linkable) p.a).breakLink(l);
			}*/
			p.a.destroy();
		}
		//for(Linkable l : set)
		//	l.transformationChanged(Placeable2D.CHANGE_LINKED_OBJECTS);
		reinsertionIndices = w.objectsDestroyed(destroyedObjects);
	}
	/**@see game.Editor2D#objectsRevived(Placeable2D[], int[])
	 * @see game.Editor2D#objectsDestroyed(Placeable2D[])*/
	public int[] getReinsertionIndices()
	{
		assert reinsertionIndices != null;
		return reinsertionIndices;
	}
	/*public LinkData[] getRestoreLinkData()
	{
	assert restoreLinkData != null;
	return restoreLinkData;
	}*/
	
	/**@see game.Editor2D#objectsRevived(Placeable2D[], int[])
	 * @see game.Editor2D#objectsDestroyed(Placeable2D[])*/
	public ArrayList<Pair<Placeable2D, ConstructorParams>> getDestroyedObjects()
	{
		assert destroyedObjects != null;
		return destroyedObjects;
	}
}